package com.itheima.reggie.web.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.config.common.BaseContext;
import com.itheima.reggie.config.common.R;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.dto.DishDto;
import com.itheima.reggie.entity.dto.PageQueryDto;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import sun.security.krb5.internal.crypto.KeyUsage;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 菜品控制器
 *
 * @Name DishController
 * @Author BaiXin
 * @Date 2022-11-02 10:00
 */
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
    @Autowired
    private DishService dishService;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 新增菜品，包括菜品和口味并检查菜品名是否重复
     *
     * @param dishDto 要新增的菜品信息DTO对象
     * @return 是否新增成功
     */
    @PostMapping
    public R save(@RequestBody DishDto dishDto) {
        //打印日志
        log.debug("新增菜品，菜品信息：[{}]", dishDto);

        //参数校验，通过统一参数校验

        //保存新菜品之前先将对应的缓存清除
        String key = new StringBuilder("dish_*_")
                .append(dishDto.getCategoryId()).append("_")
                .append(dishDto.getStatus()).append("*")
                .toString();
        //匹配查询符合要求的所有key
        Set keys = redisTemplate.keys(key);

        //删除
        redisTemplate.delete(keys);

        //调用service保存
        Boolean result = dishService.saveWithCheckNameAndSaveFlavors(dishDto);
        BaseContext.remove();
        //组织数据并返回
        if (result) {
            return R.success("新增菜品成功");
        }
        return R.error("新增菜品失败");
    }

    /**
     * 分页查询
     *
     * @param pageQueryDto 分页查询条件
     * @return 分页对象
     */
    @GetMapping("pageOrigin")
    public R<Page<Dish>> pageOrigin(PageQueryDto pageQueryDto) {
        //打印日志
        log.debug("菜品分页查询，分页条件:[{}]", pageQueryDto);
        //校验分页条件参数，统一校验

        //调用service分页查询
        Page<Dish> page = dishService.pageOrigin(pageQueryDto);
        //获得数据组织并返回
        return R.success(page);
    }

    /**
     * 分页查询
     *
     * @param pageQueryDto 分页查询条件
     * @return 分页对象
     */
    @GetMapping("page")
    public R<Page<DishDto>> page(PageQueryDto pageQueryDto) {
        //打印日志
        log.debug("菜品分页查询，分页条件:[{}]", pageQueryDto);
        //校验分页条件参数，统一校验

        //调用service分页查询
        Page<DishDto> page = dishService.page(pageQueryDto);
        //获得数据组织并返回
        return R.success(page);
    }

    /**
     * 根据id查询菜品详情
     *
     * @param id 菜品id
     * @return 菜品dto对象
     */
    @GetMapping("/{id}")
    public R<DishDto> findById(@PathVariable Long id) {
        //记录日志
        log.debug("根据id查询，id为：[{}]", id);
        //参数校验
        if (id != null) {
            //调用service查询
            DishDto dishDto = dishService.findById(id);
            //组织数据并返回
            return R.success(dishDto);
        }
        return R.error("查询失败");
    }

    /**
     * 更新
     *
     * @param dishDto 新的菜品对象
     * @return 操作是否成功
     */
    @PutMapping
    public R update(@RequestBody DishDto dishDto) {
        //记录日志
        log.debug("根据id更新菜品信息，菜品信息为:[{}]", dishDto);
        //校验id非空

        //清楚所有以分类id缓存的菜品信息（隐含条件 status）
         // dish_*_*_1*
        String key = new StringBuilder("dish_*_*_")
                .append(dishDto.getStatus()).append("*")
                .toString();

        //查找
        Set keys = redisTemplate.keys(key);

        //删除
        redisTemplate.delete(keys);

        Long id = dishDto.getId();
        if (id != null) {
            //修改菜品
            boolean result = dishService.updateByIdWithFlavors(dishDto);
            if (result) {
                return R.success("修改成功");
            } else {
                return R.error("修改失败");
            }

        }
        return R.error("参数有误");
    }

    /**
     * 批量修改状态
     *
     * @param status 修改状态值
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    public R updateStatusByIds(@PathVariable Integer status, Long[] ids) {
        log.debug("批量修改状态，状态[{}],菜品id[{}]", status, ids);

        //校验，status只能是0或者1
        if (status != 0 && status != 1) {
            return R.error("目标状态错误");
        }

        //调用service
        boolean result = dishService.switchStatus(status, ids);
        //组织数据返回
        if (result) {
            return R.success("修改状态成功");
        }
        return R.error("修改失败");
    }

    /**
     * 根据条件查询菜品
     *
     * @param dish 菜品条件
     * @return 菜品基本数据
     */
    @GetMapping("/listOlder")
    public R<List<Dish>> listOlder(Dish dish) {
        //日志记录
        log.debug("菜品条件信息：[{}]", dish);

        //传输对象不为空，不校验

        //调用service查询
        List<Dish> dishes = dishService.findByCondition(dish);

        //返回结果
        return R.success(dishes);
    }

    /**
     * 根据条件查询菜品 包含菜品口味
     *
     * @param dish 菜品条件
     * @return 菜品基本数据
     */
    @GetMapping("/list")
    public R<List<DishDto>> ist(Dish dish) {
        //日志记录
        log.debug("菜品条件信息：[{}]", dish);

        //传输对象不为空，不校验

        //构建key
        String key = new StringBuilder()
                .append("dish").append("_")
                .append(dish.getId()).append("_")
                .append(dish.getCategoryId()).append("_")
                .append(dish.getStatus()).append("_")
                .append(dish.getCode()).append("_")
                .append(dish.getDescription()).append("_")
                .append(dish.getName()).append("_")
                .toString();

        //查缓存 查到返回
        List<DishDto> dishes = (List<DishDto>) redisTemplate.opsForValue().get(key);
        if (dishes == null) {

            //查不到 mysql返回
            //调用service查询
            dishes = dishService.findByConditionAndDishFlavors(dish);

            //将结果放入缓存
            //存入redis
            redisTemplate.opsForValue().set(key, dishes, 24, TimeUnit.HOURS);
        }

        //返回结果
        return R.success(dishes);
    }

}